/*
 * Copyright 2016-2022 dromara.org.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.dromara.mendmix.gateway.component.ratelimit;

import java.util.concurrent.TimeUnit;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

/**
 * 
 * @description <br>
 * @author <a href="mailto:vakinge@gmail.com">jiangwei</a>
 * @date 2022年5月21日
 */
public class LocalRatelimiter implements RateLimiter{

	private Cache<String,com.google.common.util.concurrent.RateLimiter> limiterHub = CacheBuilder
			.newBuilder()
			.maximumSize(30000)
			.expireAfterWrite(30, TimeUnit.MINUTES)
			.build();
	
	@Override
	public boolean tryAcquire(String hitKey, double permitsPerSecond) {
		return getRateLimiter(hitKey, permitsPerSecond).tryAcquire();
	}

	
	@Override
	public void resetLimiters() {
		limiterHub.invalidateAll();
	}
	
	private com.google.common.util.concurrent.RateLimiter getRateLimiter(String hitKey, double permitsPerSecond) {
		com.google.common.util.concurrent.RateLimiter rateLimiter = limiterHub.getIfPresent(hitKey);
		if(rateLimiter != null) {
			if(rateLimiter.getRate() == permitsPerSecond) {
				limiterHub.invalidate(hitKey);
				return rateLimiter;
			}
		}
		synchronized (limiterHub) {
			rateLimiter = limiterHub.getIfPresent(hitKey);
			if(rateLimiter != null)return rateLimiter;
			rateLimiter = com.google.common.util.concurrent.RateLimiter.create(permitsPerSecond);
			limiterHub.put(hitKey, rateLimiter);
			return rateLimiter;
		}
	}

}
